package com.lxx.utils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lxx.modules.sys.entity.SysUser;


public class BeanUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class);

	
	/**
	 * 将src对象属性合并到des对象中, 即des中同名的属性会被src对应的属性覆盖,除了Null和空字符串
	 * 不能复制父类的属性
	 * @param src
	 * @param des
	 */
	public static final <T> void merge(T src, T des) {
		Map<String, Object> nameAndValues = new HashMap<>();
		
		
		Stream.of(src.getClass().getDeclaredFields()).forEach(e -> {
			try {
				Object val;
				if (e.isAccessible()) {
					val = e.get(src);
				} else {
					e.setAccessible(true);
					val = e.get(src);
					e.setAccessible(false);
				}
				if (val != null) {
					// 覆盖至des中
					nameAndValues.put(e.getName(), val);
				}
			} catch (Exception e1) {
				throw new RuntimeException(e1);
			} 
		});
		
		if (nameAndValues.isEmpty()) {
			LOGGER.warn("no attr to merge");
			return;
		}
		
		BeanUtils.setAttr(des, nameAndValues);
		
	}
	
	/**
	 * 给obj对象的属性设值
	 * 不能复制父类的属性
	 * @param obj
	 * @param filedName
	 * @param filedValue
	 */
	public static final void setAttr(Object obj, String filedName, Object filedValue) {
		if (obj == null || filedName == null) {
			throw new IllegalArgumentException("参数不能为null");
		}
		Stream.of(obj.getClass().getDeclaredFields()).forEach(e -> {
			if (e.getName().equals(filedName)) {
				try {
					if (e.isAccessible()) {
						e.set(obj, filedValue);
					} else {
						e.setAccessible(true);
						e.set(obj, filedValue);
						e.setAccessible(false);
					}
				} catch (Exception e1) {
					throw new RuntimeException(e1);
				} 
				return;
			}
		});
	}
	
	/**
	 * 给obj对象的属性设值
	 * 不能复制父类的属性
	 * @param obj
	 * @param args  属性名和属性值的map
	 */
	public static final void setAttr(Object obj, Map<String, Object> args) {
		if (obj == null || args.isEmpty()) {
			throw new IllegalArgumentException("参数不合法");
		}
		Stream.of(obj.getClass().getDeclaredFields()).forEach(e -> {
			if (args.containsKey(e.getName())) {
				try {
					if (e.isAccessible()) {
						e.set(obj, args.get(e.getName()));
					} else {
						e.setAccessible(true);
						e.set(obj, args.get(e.getName()));
						e.setAccessible(false);
					}
				} catch (Exception e1) {
					throw new RuntimeException(e1);
				} 
			}
		});
	}
	
	public static void main(String[] args) {
		SysUser user = new SysUser();
		SysUser user1 = new SysUser();
		
		user.setFullName("zhangsan");
		user1.setFullName("lisi");
		user1.setCaptcha("aabb");
		
		BeanUtils.merge(user, user1);
		
		System.out.println(user);
		System.out.println(user1);
		
	}
}
